package com.amigo.online.provider.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.amigo.online.common.base.security.LocalUser;
import com.amigo.online.common.base.service.BaseService;
import com.amigo.online.common.core.response.Response;
import com.amigo.online.common.core.response.StatusCode;
import com.amigo.online.common.param.RedisKey;
import com.amigo.online.common.param.common.MqTag;
import com.amigo.online.common.param.dto.adv.AdvNearbyDto;
import com.amigo.online.common.param.dto.login.LoginByIdDto;
import com.amigo.online.common.param.dto.user.*;
import com.amigo.online.common.param.result.*;
import com.amigo.online.common.param.result.VideoInfo.VideoUserInfo;
import com.amigo.online.common.param.result.adv.AroundPersonAdvInfo;
import com.amigo.online.common.util.CommonValidator;
import com.amigo.online.common.util.DistanceHandleUtil;
import com.amigo.online.common.util.Md5Util;
import com.amigo.online.common.util.StringUtils;
import com.amigo.online.provider.user.common.ConstantValue;
import com.amigo.online.provider.user.common.GlobalController;
import com.amigo.online.provider.user.common.RwRedisService;
import com.amigo.online.provider.user.exception.UserException;
import com.amigo.online.provider.user.mapper.*;
import com.amigo.online.provider.user.model.entity.*;
import com.amigo.online.provider.user.model.entity.db.RegisterTbl;
import com.amigo.online.provider.user.model.entity.db.UserOneSignalExample;
import com.amigo.online.provider.user.mongo.dao.UserDao;
import com.amigo.online.provider.user.mongo.dao.UserRepository;
import com.amigo.online.provider.user.mongo.entity.Loc;
import com.amigo.online.provider.user.mongo.entity.MyUserEntity;
import com.amigo.online.provider.user.mongo.entity.UserEntity;
import com.amigo.online.provider.user.rocketmq.RocketMqUtil;
import com.amigo.online.provider.user.rocketmq.model.BaseMqSendModel;
import com.amigo.online.provider.user.service.*;
import com.amigo.online.provider.user.util.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Preconditions;
import com.mongodb.BasicDBObject;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCursor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RandomStringUtils;

import org.apache.ibatis.annotations.Param;
import org.bson.Document;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.text.ParseException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
@SuppressWarnings({"unchecked"})
@Slf4j
public class UserServiceImpl extends BaseService<User> implements UserService {

    @Autowired
    private BlackService blackService;
    @Autowired
    private VIPService vipService;
    @Resource
    private UserMapper userMapper;
    @Autowired
    BlackMapper blackmapper;
    @Resource
    private UserPhotosMapper userPhotosMapper;
    @Resource
    private VerificationCodeService verificationCodeService;
    @Resource
    private TokenManagerService tokenManagerService;
    @Autowired
    RwRedisService rwRedisService;
    @Resource
    private UserAreaInfoService userAreaInfoService;
    @Autowired
    AdvFeignService advFeignService;
    @Autowired
    InviteCodeMapper inviteCodeMapper;
    @Autowired
    InviteCodeRecordMapper inviteCodeRecordMapper;
    @Autowired
    RecordDeviceMapper recordDeviceMapper;
    @Autowired
    RegisterTblMapper registerTblMapper;
    @Autowired
    TanService tanService;
    @Value("${google.map.key}")
    String googleMapKey;
    private static String prettyNums[] = {"01234", "12345", "23456", "34567", "45678", "56789", "43210", "54321",
            "65432", "76543", "87654", "98765", "00000", "11111", "22222", "33333", "55555", "66666", "77777", "88888",
            "99999"};
    @Autowired
    private UserDao userDao;
    @Resource
    private FollowMapper followMapper;
    @Resource
    private UserHobbyMapper userhobbyMapper;
    @Autowired
    FollowService followService;
    private static String user_key = RedisKey.USER_REDIS_KEY;
    @Autowired
    FeignResponseConvertService<AroundPersonAdvInfo> feignResponseConvertService;
    @Autowired
    @Qualifier("writeMongoTemplate")
    MongoTemplate writeMongoTemplate;
    @Autowired
    UserOneSignalMapper userOneSignalMapper;
    @Override
    public boolean accountExist(String account, Integer type) {
        if (StringUtils.isEmpty(account)) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        User user = new User();
        if (type.intValue() == 1) {
            Example example = new Example(User.class);
            example.createCriteria().andIn("mobilephone", StandardizePhoneUtil.standard(account));
            return userMapper.selectCountByExample(example) <= 0;
        } else if (type.intValue() == 2) {
            user.setAccount(account);
            return userMapper.selectCount(user) <= 0;
        } else if (type.intValue() == 3) {
            user.setEmail(account);
            return userMapper.selectCount(user) <= 0;
        } else if (type.intValue() == 4) {
            user.setFacebookOpenId(account);
            return userMapper.selectCount(user) <= 0;
        } else {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
    }

    @Override
    public LoginInfo register(String mobilephone, String countryCode, String code, String password, String password2, String registerCode,
                              Double[] point) {
        Preconditions.checkArgument(!StringUtils.isEmpty(mobilephone), StatusCode.MOBILEPHONE_NOT_EMPTY.msg());
        Preconditions.checkArgument(!StringUtils.isEmpty(countryCode), StatusCode.BAD_REQUEST.msg());
        Preconditions.checkArgument(!StringUtils.isEmpty(code), StatusCode.SMS_CODE_NOT_EMPTY.msg());
        Preconditions.checkArgument(!StringUtils.isEmpty(password), StatusCode.PASSWORD_NOT_EMPTY.msg());
        Preconditions.checkArgument(password.equals(password2), StatusCode.PASSWORD_MUST_SAME.msg());
        if (!accountExist(mobilephone, 1)) {
            throw new UserException(StatusCode.MOBILEPHONE_EXIST);
        }
        verificationCodeService.checkSmsCode(mobilephone, code, 1);

        User user = new User();
        // user.setAccount(StringUtils.generateAccountString());
        user.setAccountDefault(1);
        user.setMobilephone(mobilephone);
        user.setSex("UN");
        user.setCountryCode(countryCode);
        user.setPassword(password);
        user.setPasswordHash(Md5Util.encrypt(password));
        user.setPasswordDefault(0);
        user.setCountry(0);
        user.setProvince(0);
        user.setCity(0);
        user.setHomeCity(0);
        user.setHomeCountry(0);
        user.setHomeProvince(0);
        user.setType(1);
        //使用注册码注册为模特用户
        if(registerCode != null){
            RegisterTbl registerTbl = registerTblMapper.selectByPrimaryKey(registerCode);
            if (registerTbl!=null && registerTbl.getUserId()==null){
                user.setType(3);
            }else {//注册码异常
                throw new UserException(StatusCode.REGISTER_CODE_ERROR);
            }
        }

        user.setVip(0);
        user.setStatus(1);
        user.setLove(0);
        user.setVerified(0);
        user.setCelebrity(0);
        user.setVerifiedTime(0L);
        user.setSecret(0);
        user.setNotifyComment(1);
        user.setNotifyZan(1);
        user.setNotifyGroup(1);
        user.setNotifyVoice(1);
        user.setNotifyFollow(1);
        user.setHome("");
        user.setOpenT(0);
        user.setSexModified(0);
        long nowSeconds = System.currentTimeMillis() / 1000;
        user.setBirthday(nowSeconds - 569203200);
        user.setCreatedTime(nowSeconds);
        user.setUpdatedTime(nowSeconds);
        if (userMapper.insert(user) <= 0) {
            throw new UserException(StatusCode.NEW_USER_FAILED);
        }

        user.setAccount(getNotPrettyAccount(user.getId())); // 只有插入数据库后才能拿到ID
        // 用户注册完成后,补上account
        User record = new User();
        record.setId(user.getId());
        record.setAccount(user.getAccount());
        userMapper.updateByPrimaryKeySelective(record);
        //更新注册码
        if(registerCode != null){
            RegisterTbl registerTbl = registerTblMapper.selectByPrimaryKey(registerCode);
            if (registerTbl!=null & registerTbl.getUserId()==null){
                registerTbl.setUserId(user.getId());
                registerTblMapper.updateByPrimaryKey(registerTbl);
            }else {//注册码异常
                throw new UserException(StatusCode.REGISTER_CODE_ERROR);
            }
        }
        UserInfo u = ConvertUtil.UserToUserInfo(user);

        String token = tokenManagerService.createToken(u);
        LoginInfo info = new LoginInfo();
        info.setToken(token);
        info.setCompleted(false);
        return info;
    }

    // 获取account号，规则是 ID+600000,并且避开靓号(暂定为prettyNums)
    private String getNotPrettyAccount(Long nowId) {
        String nowAccountStr = String.valueOf(nowId + 600000);
        for (String num : prettyNums) {
            int lastIndex = nowAccountStr.lastIndexOf(num);
            if (lastIndex >= 0) {
                int lastCount = nowAccountStr.length() - num.length() - lastIndex;
                double newId = Integer.valueOf(nowAccountStr) + Math.pow(10, lastCount);
                return (long) newId + "";
            }
        }
        return nowAccountStr;
    }

    /**
     * 创建默认用户
     *
     * @param user
     * @return
     */
    public User createUser(User user) {
        Long id = getNotPrettyId();
        user.setId(id);
        user.setAccount(String.valueOf(id));
        user.setAccountDefault(1);
        user.setSex("UN");
        String user_password = RandomStringUtils.randomAlphanumeric(10);
        user.setPassword(user_password);
        user.setPasswordHash(Md5Util.encrypt(user_password));
        user.setPasswordDefault(1);
        user.setCountry(0);
        user.setProvince(0);
        user.setCity(0);
        user.setHomeCity(0);
        user.setHomeCountry(0);
        user.setHomeProvince(0);
        user.setType(1);
        user.setVip(0);
        user.setStatus(1);
        user.setLove(0);
        user.setVerified(0);
        user.setCelebrity(0);
        user.setVerifiedTime(0L);
        user.setSecret(0);
        user.setNotifyComment(1);
        user.setNotifyZan(1);
        user.setNotifyGroup(1);
        user.setNotifyVoice(1);
        user.setNotifyFollow(1);
        user.setHome("");
        user.setOpenT(0);
        user.setSexModified(0);
        long nowSeconds = System.currentTimeMillis() / 1000;
        user.setCreatedTime(nowSeconds);
        user.setUpdatedTime(nowSeconds);
        user.setBirthday(nowSeconds - 569203200);// 默认按照每年366天算
        if (userMapper.insert(user) <= 0) {
            throw new UserException(StatusCode.LOGIN_FAIL);
        }
        user.setAccount(getNotPrettyAccount(user.getId())); // 只有插入数据库后才能拿到ID

        // 用户注册完成后,补上account
        User record = new User();
        record.setId(user.getId());
        record.setAccount(user.getAccount());
        userMapper.updateByPrimaryKeySelective(record);

        return user;
    }

    private Long getNotPrettyId() {
        Long nowId = userMapper.getNextId();
        String nowIdStr = String.valueOf(nowId);
        for (String num : prettyNums) {
            int lastIndex = nowIdStr.lastIndexOf(num);
            if (lastIndex >= 0) {
                int lastCount = nowIdStr.length() - num.length() - lastIndex;
                double newId = Integer.valueOf(nowIdStr) + Math.pow(10, lastCount);
                return (long) newId;
            }
        }
        return nowId;
    }

    @Override
    public LoginInfo login(Integer type, String username, String password, Double[] point, String platform,
                           String version, String device) {
        Preconditions.checkArgument(!StringUtils.isEmpty(username), StatusCode.MOBILEPHONE_NOT_EMPTY.msg());
        User user = null;
        if (type.intValue() == 1) { // 手机号密码登陆
            user = userMapper.findByMobilephone(username);
            if (user == null) {
                throw new UserException(StatusCode.MOBILEPHONE_NOT_EXIST);
            } else {
                Long tipoff = userMapper.checkTipOff(user.getId());
                if (tipoff != null && tipoff > 0) {
                    throw new UserException(StatusCode.ACCOUNT_FORBIDDEN);
                }
            }
            Preconditions.checkArgument(!StringUtils.isEmpty(password), StatusCode.PASSWORD_NOT_EMPTY.msg());
            if (!Md5Util.matches(password, user.getPasswordHash())) {
                logger.info(password + "------" + user.getPasswordHash());
                throw new UserException(StatusCode.PASSWORD_ERROR);
            }
        } else if (type.intValue() == 2) { // 短信登陆
            Preconditions.checkArgument(!StringUtils.isEmpty(password), StatusCode.SMS_CODE_NOT_EMPTY.msg());
            verificationCodeService.checkSmsCode(username, password, 2);
            user = userMapper.findByMobilephone(username);
            // 不存在创建用户
            if (user == null) {
                String countryCode = verificationCodeService.getMobilephoneCountryCode(username, password, 2);
                if (countryCode == null) {
                    throw new UserException(StatusCode.LOGIN_FAIL);
                }
                user = new User();
                user.setMobilephone(username);
                user.setCountryCode(countryCode);
                user = createUser(user);
            } else {
                Long tipoff = userMapper.checkTipOff(user.getId());
                if (tipoff != null && tipoff > 0) {
                    throw new UserException(StatusCode.ACCOUNT_FORBIDDEN);
                }
            }
        } else if (type.intValue() == 3) { // facebook登陆
            user = userMapper.findByFacebookOpenId(username);
            // 不存在直接创建用户
            if (user == null) {
                user = new User();
                user.setFacebookOpenId(username);
                user = createUser(user);
            } else {
                Long tipoff = userMapper.checkTipOff(user.getId());
                if (tipoff != null && tipoff > 0) {
                    throw new UserException(StatusCode.ACCOUNT_FORBIDDEN);
                }
            }
        }
        // 判断以前的token
        if (StringUtils.isNotBlank(user.getToken())) {
            rwRedisService.delete(user.getToken());
        }
        UserInfo userInfo = ConvertUtil.UserToUserInfo(user);
        userInfo.setDevice(device);
        // 获得用户相册
        List<UserPhotos> list = userPhotosMapper.getListByUid(userInfo.getId());
        List<PhotoInfo> plist = ConvertUtil.UserPhotosToPhotoInfo(list);
        // 获得相册中的第一张人脸图
        PhotoInfo pss = getFirstImg(plist);
        userInfo.setPhotos(plist);
        // 获得用户爱好
        List<UserHobby> hobby = userhobbyMapper.findHobbyByUserId(userInfo.getId());
        ArrayList<HobbyInfo> hobbys = ConvertUtil.HobbyToHobbyInfo(hobby);
        userInfo.setHobbylist(hobbys);
        // 判断是否是商家
        Long merchantId = userMapper.checkMerchant(userInfo.getId());
        if (merchantId != null) {
            userInfo.setMerchantId(merchantId);
        }
//		rwRedisService.opsForHash().put(user_key, u.getId(), u);
        String token = tokenManagerService.createToken(userInfo);
        user.setToken(token);
        userMapper.updateByPrimaryKeySelective(user);
        LoginInfo info = new LoginInfo();
        info.setToken(token);
        info.setCompleted(true);

        if (StringUtils.isEmpty(user.getNickname()) || StringUtils.isEmpty(user.getAvatar())) {
            // 信息未完善
            info.setCompleted(false);
        } else {
            Update update = new Update().set("platform", platform).set("version", version).set("device", device);
            if (point[0] != 0 && point[1] != 0) {
                update.set("loc.coordinates", point);
            } else {
                // TODO: 2019/10/10
                // 传过来是0 则先判断原来经纬度 还是0 放到Ron总30344L地理位置处
                try {
                    point = userDao.getUserById(userInfo.getId()).getLoc().getCoordinates();
                    if (ArrayUtils.isEmpty(point) || point.length != 2) {
                        point = new Double[]{0.0, 0.0};
                    }
                    if (point[0] == 0 && point[1] == 0) {
                        point = userDao.getUserById(30334L).getLoc().getCoordinates();
                    }
                    update.set("loc.coordinates", point);
                } catch (NullPointerException e) {
                    // 防止Facebook登陆的新用户 mongo里没有
                    logger.error("用户未同步,id:{}", userInfo.getId());
                }
            }
            userDao.updateUserInfo(userInfo.getId(), update);
        }
//        MIMCHttpUtil.rmToken(user.getId().toString());
        logger.info("登陆成功,type:{},返回的token:{},userId:{}", type, info.getToken(), user.getId());
        return info;
    }

    private PhotoInfo getFirstImg(List<PhotoInfo> plist) {
        List<PhotoInfo> plists = plist.stream().filter(e -> e.getFirstImg() == 1).collect(Collectors.toList());
        PhotoInfo pss = new PhotoInfo();
        pss.setPhoto("");
        pss.setCheck(0);
        if (plists != null && plists.size() >= 1) {
            pss = plists.get(0);
        }
        return pss;
    }

    @Override
    public boolean complete(Long age, String nickname, String sex, String avatar, Double[] point, String platform,
                            String version, String device, String inviteCode) {
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            logger.error("");
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserInfo u = info.getUser();
        if (!CommonValidator.validate(u)) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        User user = userMapper.selectByPrimaryKey(u.getId());
        if (user == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        user.setSex(sex);
        user.setNickname(nickname);
        user.setAvatar(avatar);
        user.setBirthday(age);
        // user.setAvatarSmall(avatarSmall);
        if (userMapper.updateByPrimaryKeySelective(user) <= 0) {
            throw new UserException(StatusCode.USER_COMPETE_FAILED);
        }
        u.setAvatar(avatar);
        u.setSex(sex);
        u.setNickname(nickname);
        u.setDevice(device);
        u.setBirthday(age);
        rwRedisService.opsForHash().delete(user_key, u.getId());

        info.setUser(u);
        tokenManagerService.updateUser(info);

        // 完善部分信息
        Update update = new Update().set("platform", platform).set("version", version).set("device", device);
        if (point[0] != 0 && point[1] != 0) {
            update.set("loc.coordinates", point);
        }
        userDao.updateUserInfo(u.getId(), update);

        if (avatar != null) {
            RocketMqUtil.send(new BaseMqSendModel.Builder().beanName("CompressionAvatar").tag(MqTag.USER)
                    .sendContentBean(u.getId()).build());
        }

        // 使用了邀请码
        if (StringUtils.isNotBlank(inviteCode)) {
            useInviteCode(inviteCode);
        }

        // 把头像同步到个人相册的第一张图
        tanService.newUserPhoto(avatar, 1, 1);
        return true;
    }

    @Override
    public boolean updateUserInfo(UserInfoDto dto) {
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserInfo u = info.getUser();
        if (u.getId() == null || u.getId().intValue() <= 0) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        User user = userMapper.selectByPrimaryKey(u.getId());
        if (user == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserEntity muser = userDao.getUserById(user.getId());
        if (muser == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        boolean flag = false;
        boolean mFlag = false;
        boolean uFlag = false;
        if (StringUtils.isNotEmpty(dto.getNickname())) {
            user.setNickname(dto.getNickname());
            muser.setNickname(dto.getNickname());
            u.setNickname(dto.getNickname());
            uFlag = true;
            mFlag = true;
            flag = true;
        }
        if (StringUtils.isNotEmpty(dto.getSex())) {
            user.setSex(dto.getSex());
            muser.setSex(dto.getSex());
            u.setSex(dto.getSex());
            uFlag = true;
            mFlag = true;
            flag = true;
        }
        if (dto.getCountry() != null && !dto.getCountry().equals(0)) {
            user.setCountry(dto.getCountry());
            u.setCountry(dto.getCountry());
            uFlag = true;
            flag = true;
        }
        if (dto.getProvince() != null && !dto.getProvince().equals(0)) {
            user.setProvince(dto.getProvince());
            u.setProvince(dto.getProvince());
            uFlag = true;
            flag = true;
        }
        if (dto.getCity() != null && !dto.getCity().equals(0)) {
            user.setCity(dto.getCity());
            u.setCity(dto.getCity());
            uFlag = true;
            flag = true;
        }
        if (dto.getHomeCountry() != null && !dto.getHomeCountry().equals(0)) {
            user.setHomeCountry(dto.getHomeCountry());
            u.setHomeCountry(dto.getHomeCountry());
            uFlag = true;
            flag = true;
        }
        if (dto.getHomeProvince() != null && !dto.getHomeProvince().equals(0)) {
            user.setHomeProvince(dto.getHomeProvince());
            u.setHomeProvince(dto.getHomeProvince());
            uFlag = true;
            flag = true;
        }
        if (dto.getHomeCity() != null && !dto.getHomeCity().equals(0)) {
            user.setHomeCity(dto.getHomeCity());
            u.setHomeCity(dto.getHomeCity());
            uFlag = true;
            flag = true;
        }

        if (StringUtils.isNotEmpty(dto.getCompany())) {
            user.setCompany(dto.getCompany());
            u.setCompany(dto.getCompany());
            uFlag = true;
            flag = true;
        }
        if (StringUtils.isNotEmpty(dto.getJob())) {
            user.setJob(dto.getJob());
            u.setJob(dto.getJob());
            uFlag = true;
            mFlag = true;
            flag = true;
        }
        if (dto.getSchool() != null) {
            user.setSchool(dto.getSchool());
            u.setSchool(dto.getSchool());
            flag = true;
            uFlag = true;
        }
        if (StringUtils.isNotEmpty(dto.getSign())) {
            user.setSign(dto.getSign());
            muser.setSign(dto.getSign());
            u.setSign(dto.getSign());
            uFlag = true;
            mFlag = true;
            flag = true;
        }
        if (StringUtils.isNotEmpty(dto.getAvatar())) {
            user.setAvatar(dto.getAvatar());
            muser.setAvatar(dto.getAvatar());
            u.setAvatar(dto.getAvatar());
            uFlag = true;
            mFlag = true;
            flag = true;
        }
        /*
         * if (StringUtils.isNotEmpty(dto.getAvatarSmall())) {
         * user.setAvatar(dto.getAvatarSmall()); muser.setAvatar(dto.getAvatarSmall());
         * u.setAvatar(dto.getAvatarSmall()); uFlag = true; mFlag = true; flag = true; }
         */
        if (StringUtils.isNotEmpty(dto.getBackground())) {
            user.setBackground(dto.getBackground());
            u.setBackground(dto.getBackground());
            uFlag = true;
            flag = true;
        }
        if (dto.getLove() != null && !dto.getLove().equals(0)) {
            user.setLove(dto.getLove());
            u.setLove(dto.getLove());
            uFlag = true;
            flag = true;
        }
        if (dto.getBirthday() != null && !dto.getBirthday().equals(0L)) {
            user.setBirthday(dto.getBirthday());
            muser.setBirthday(dto.getBirthday());
            u.setBirthday(dto.getBirthday());
            uFlag = true;
            mFlag = true;
            flag = true;
        }
        if (dto.getSecret() != null) {
            user.setSecret(dto.getSecret());
            u.setSecret(dto.getSecret());
            muser.setSecret(dto.getSecret());
            uFlag = true;
            mFlag = true;
            flag = true;
        }
        if (dto.getHome() != null) {
            user.setHome(dto.getHome());
            u.setHome(dto.getHome());
            uFlag = true;
            flag = true;
        }
        if (flag) {
            if (userMapper.updateByPrimaryKeySelective(user) <= 0) {
                throw new UserException(StatusCode.USER_UPDATE_FAILED);
            }
            /*
             * 异步处理 if (mFlag) { long result = userDao.updateUser(muser); if (result == 0) {
             * logger.error("用户信息更新失败，失败的用户ID:" + muser.getId()); } }
             */
            if (uFlag) {
                info.setUser(u);
                /*
                 * 异步处理 RocketMqUtil.send(MqTag.ROCKETMQ_BEAN_USERTOSOLR, u, MqTag.SEARCH);
                 */
                tokenManagerService.updateUser(info);
                UserInfo tempInfo = (UserInfo) rwRedisService.hget(user_key, u.getId());
                if (tempInfo != null) {
                    u.setDevice(tempInfo.getDevice());
                }
                rwRedisService.opsForHash().delete(user_key, u.getId());
            }
        }

        try {
            if (dto.getAvatar() != null) {
                RocketMqUtil.send(new BaseMqSendModel.Builder().beanName("CompressionAvatar").tag(MqTag.USER)
                        .sendContentBean(u.getId()).build());
            }
        } catch (Exception e) {
            logger.error("用户头像压缩处理,MQ消息发送失败:" + u.getId());
        }

        return true;
    }

    @Override
    public UserInfo getUserInfo() {
        Long id = GlobalController.getNowUser().getId();
        UserInfo userInfo = getUserById(id);
        logger.info("我的个人中心返回的值 : {}", JSONObject.toJSONString(userInfo));
        return userInfo;
    }

    @Override
    public boolean updateUserAccount(String account) {
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserInfo userInfo = info.getUser();
        if (userInfo.getId() == null || userInfo.getId().intValue() <= 0) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }

        // 判断是否是靓号
        for (String num : prettyNums) {
            if (account.contains(num)) {
                logger.info(account + "不能为靓号，违反了:" + num);
                throw new UserException(StatusCode.ACCOUNT_EXIST);
            }
        }

        User user = userMapper.selectByPrimaryKey(userInfo.getId());
        if (user == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        // 3为不可再修改
        if (user.getAccountDefault().equals(3)) {
            logger.info("AccountDefault=" + user.getAccountDefault() + ",不可再修改了");
            return false;
        }

        if (userMapper.findByAccount(account) != null) {
            throw new UserException(StatusCode.ACCOUNT_EXIST);
        }
        user.setAccount(account);
        long nowSeconds = System.currentTimeMillis() / 1000;
        user.setUpdatedTime(nowSeconds);
        if (userMapper.updateAccount(user) <= 0) {
            throw new UserException(StatusCode.USER_UPDATE_FAILED);
        }
        userInfo.setAccount(account);
        userInfo.setAccountDefault(userInfo.getAccountDefault() + 1);
        info.setUser(userInfo);
        tokenManagerService.updateUser(info);
        UserInfo tempInfo = (UserInfo) rwRedisService.hget(user_key, userInfo.getId());
        if (tempInfo != null) {
            userInfo.setDevice(tempInfo.getDevice());
        }
        rwRedisService.opsForHash().delete(user_key, userInfo.getId());
        Map<String, String> updateMap = new HashMap<>(16);
        updateMap.put("id", String.valueOf(userInfo.getId()));
        updateMap.put("account", account);

        /*
         * 异步处理 RocketMqUtil.send(MqTag.ROCKETMQ_BEAN_USERPARTTOSOLR, u, MqTag.SEARCH);
         */

        return true;
    }

    @Override
    public UserInfo getUserById(Long id) {
        logger.info("userId : {}", id);
//		UserInfo userInfo = (UserInfo) rwRedisService.hget(user_key, id);
//		if (userInfo != null){
//			logger.info("缓存中的值 : {}", JSONObject.toJSONString(userInfo));
//			return userInfo;
//		}
        User mysqlUser = userMapper.selectByPrimaryKey(id);
        if (mysqlUser == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        // 用户照片
        List<UserPhotos> photolist = userPhotosMapper.getListByUid(id);
        //去重
        photolist = removeDuplicate(photolist);
        // 用户爱好
        List<UserHobby> hobbylist = userhobbyMapper.findHobbyByUserId(id);
        // 是否是商家
        Long merchantId = userMapper.checkMerchant(id);
        UserInfo userInfo = ConvertUtil.UserToUserInfo(mysqlUser);
        userInfo.setMerchantId(merchantId == null ? 0L : merchantId);
        userInfo.setPhotos(ConvertUtil.UserPhotosToPhotoInfo(photolist));
        userInfo.setHobbylist(ConvertUtil.HobbyToHobbyInfo(hobbylist));
        rwRedisService.opsForHash().put(user_key, id, userInfo);

        VipInfo vipInfo = vipService.getVipInfo(id);

        userInfo.setHonoured(vipInfo.isVip());
        userInfo.setVipEndTime(vipInfo.getEndTime());
        return userInfo;
    }


    @Override
    public ResponseEntity<Response> updateLoginPath(Double[] point) {
        if(point[0]!=0&&point[1]!=0) {
            Update update = new Update();
            update.set("loc.coordinates", point);
            //用户是模特
            if(GlobalController.getNowUser()!=null && GlobalController.getNowUser().getType()!=null && GlobalController.getNowUser().getType().equals(3)){
                String short_name;
                UserEntity userEntity = userDao.getUserById(GlobalController.getNowUser().getId());
                Double[] coordinates = userEntity.getLoc().getCoordinates();
                if(abs(coordinates[0]- point[0])>0.5 || abs(coordinates[1]- point[1])>0.5 ){
                    try{
                        log.info("发送请求：" + "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + point[1] + "," + point[0] + "&key="+ googleMapKey );
                        JSONObject jsonObject = new RestTemplate().getForObject("https://maps.googleapis.com/maps/api/geocode/json?latlng=" + point[1] + "," + point[0] + "&key="+ googleMapKey, JSONObject.class);
                        log.info("返回值：" + jsonObject.toJSONString());
                        JSONArray addressComponents = jsonObject.getJSONArray("results").getJSONObject(1).getJSONArray("address_components");
                        for(int i = 0; i<addressComponents.size(); i++){
                            if(addressComponents.getJSONObject(i).getJSONArray("types").getString(0).equals("locality")){
                                short_name=addressComponents.getJSONObject(i).getString("short_name");
                                update.set("cityName", short_name);
                                User user = new User();
                                user.setId(GlobalController.getNowUser().getId());
                                user.setCityName(short_name);
                                userMapper.updateByPrimaryKeySelective(user);
                                log.info(short_name);
                                break;
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
            userDao.updateUserInfo(GlobalController.getNowUser().getId(), update);
        }
        return null;
    }
    public static double abs(double a) {
        return (a < 0) ? -a : a;
    }
    @Override
    public void checkInvite() {
        List<InvitePeople> list = userMapper.selectInviteNum();
        if( list != null){
            if(list.size()>0){
                StringBuffer stringBuffer = new StringBuffer();
                for(int i =0 ;i<list.size();i++){
                    stringBuffer.append(i+1+":");
                    stringBuffer.append(" 用户ID：");
                    stringBuffer.append(list.get(i).getId());
                    stringBuffer.append(" 用户昵称：");
                    stringBuffer.append(list.get(i).getNickname());
                    stringBuffer.append(" 用户手机号:");
                    stringBuffer.append(list.get(i).getMobilephone());
                    stringBuffer.append("     ");
                }
                String text = new String(stringBuffer);
            sendMail("lhtdeg@gmail.com",text,"有用户邀请过多");
//                sendMail("274011288@qq.com",text,"有用户邀请过多");
            }
        }
    }

    public static boolean sendMail(String to, String text, String title) {
        String from = "tevitalkinvite@163.com"; // 发件人邮箱地址
        String user = "tevitalkinvite@163.com"; // 发件人称号，同邮箱地址
        String password = "amigo123456"; // 发件人邮箱客户端授权码

        Properties props = new Properties();
        props.setProperty("mail.smtp.host", "smtp.163.com"); // 设置发送邮件的邮件服务器的属性（这里使用网易的smtp服务器）
        props.put("mail.smtp.host", "smtp.163.com"); // 需要经过授权，也就是有户名和密码的校验，这样才能通过验证（一定要有这一条）
        props.put("mail.smtp.auth", "true"); // 用刚刚设置好的props对象构建一个session
        Session session = Session.getDefaultInstance(props); // 有了这句便可以在发送邮件的过程中在console处显示过程信息，供调试使
        // 用（你可以在控制台（console)上看到发送邮件的过程）
        session.setDebug(true); // 用session为参数定义消息对象
        MimeMessage message = new MimeMessage(session); // 加载发件人地址
        try {
            message.setFrom(new InternetAddress(from));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // 加载收件人地址
            message.setSubject(title); // 加载标题
            Multipart multipart = new MimeMultipart(); // 向multipart对象中添加邮件的各个部分内容，包括文本内容和附件
            BodyPart contentPart = new MimeBodyPart(); // 设置邮件的文本内容
            contentPart.setContent(text, "text/html;charset=utf-8");
            multipart.addBodyPart(contentPart);
            message.setContent(multipart);
            message.saveChanges(); // 保存变化
            Transport transport = session.getTransport("smtp"); // 连接服务器的邮箱
            transport.connect("smtp.163.com", user, password); // 把邮件发送出去
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();
        } catch (MessagingException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public   static   List<UserPhotos>  removeDuplicate(List<UserPhotos> list)  {
        for  ( int  i  =   0 ; i  <  list.size()  -   1 ; i ++ )  {
            for  ( int  j  =  list.size()  -   1 ; j  >  i; j -- )  {
                if  (list.get(j).getPhoto().equals(list.get(i).getPhoto()))  {
                    list.remove(j);
                }
            }
        }
        return list;
    }

    @Override
    public UserIndexInfo getUserInfoById(Long id) {
        // 当前用户
        UserInfo loginedUser = GlobalController.getNowUser();
        // 返回用户信息
        UserInfo userInfo = getUserById(id);
        // 判断双方的探探开启状态 决定是否显示照片
///		if(loginedUser.getOpenT()!=1 || userInfo.getOpenT()!=1) {
//			userInfo.setHobbylist(new ArrayList<>());
//			userInfo.setPhotos(new ArrayList<>());
//		}
        // 判断双方的 关注关系 拉黑关系
        UserIndexInfo userIndexInfo = new UserIndexInfo();
        BeanUtils.copyProperties(userInfo, userIndexInfo);
        //我有没有拉黑他
        if (blackService.isblack(id)) {
            userIndexInfo.setBlacked(true);
        }
        Follow concernFollow = followMapper.checkConcernSingle(id, loginedUser.getId());
        if (null != concernFollow && concernFollow.getCanceled().equals(0)) {
            userIndexInfo.setFollowed(true);
        }
        // 获得对方用户的mongo信息(上次登陆时间、双方距离)
        userIndexInfo = getDetailInfoFromMongo(userIndexInfo, loginedUser);
        VipInfo vipInfo = vipService.getVipInfo(id);
        userIndexInfo.setHonoured(vipInfo.isVip());
        userIndexInfo.setVipEndTime(vipInfo.getEndTime());
        return userIndexInfo;
    }

    private UserIndexInfo getDetailInfoFromMongo(UserIndexInfo userIndexInfo, UserInfo loginedUser) {
        List<UserEntity> users = userDao
                .getUsersByIds(Arrays.asList(new Long[]{userIndexInfo.getId(), loginedUser.getId()}));
        Double distance = 0d;
        Double localUserlng = 0d;
        Double localUserlat = 0d;
        Double userlng = 0d;
        Double userlat = 0d;
        try {
            localUserlng = users.get(0).getLoc().getCoordinates()[0];
            localUserlat = users.get(0).getLoc().getCoordinates()[1];
            // 兼容自己查看自己
            if (users.size() == 2) {
                userlng = users.get(1).getLoc().getCoordinates()[0];
                userlat = users.get(1).getLoc().getCoordinates()[1];
            } else {
                userlng = users.get(0).getLoc().getCoordinates()[0];
                userlat = users.get(0).getLoc().getCoordinates()[1];
            }
        } catch (Exception e) {
            logger.error("数据异常");
            e.printStackTrace();
        }
        distance = LocationUtils.getDistance(localUserlat, localUserlng, userlat, userlng);
        String dis = DistanceHandleUtil.convertDoubleToStringFormat(distance);
        // 根据隐私设置给距离
        if (userIndexInfo.getSecret() == 0) {
            // 所有人可见
            userIndexInfo.setDistance(distance);
            userIndexInfo.setDis(dis);
        } else if (userIndexInfo.getSecret() == 1) {
            // 好友可见
            if (followService.checkIsFriend(loginedUser.getId(), userIndexInfo.getId())) {
                userIndexInfo.setDistance(distance);// 是好友
                userIndexInfo.setDis(dis);
            } else {
                userIndexInfo.setDis("");
            }
        } else {
            userIndexInfo.setDis("");
        }
        for (UserEntity userEntity : users) {
            if (userEntity.getId().equals(userIndexInfo.getId())) {
                userIndexInfo.setLastLoginTime(userEntity.getLoginTime());
            }
        }
        return userIndexInfo;
    }

    @Override
    public UserInfo getUserInfoByToken(String token) {
        UserInfo userInfo = GlobalController.getNowUser();
        return getUserById(userInfo.getId());
    }

    @Override
    public boolean updateUserPassword(PasswordDto dto) {
        if (dto == null) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        if (dto.getCode() == null || StringUtils.isEmpty(dto.getCode())) {
            throw new UserException(StatusCode.SMS_CODE_NOT_EMPTY);
        }

        if (dto.getPassword() == null || StringUtils.isEmpty(dto.getPassword())) {
            throw new UserException(StatusCode.PASSWORD_NOT_EMPTY);
        }
        if (!dto.getPassword().equals(dto.getPassword2())) {
            throw new UserException(StatusCode.PASSWORD_MUST_SAME);
        }
        UserInfo u = GlobalController.getNowUser();
        User user = userMapper.selectByPrimaryKey(u.getId());
        verificationCodeService.checkSmsCode(user.getMobilephone(), dto.getCode(), 3);
        user.setPassword(dto.getPassword());
        user.setPasswordHash(Md5Util.encrypt(dto.getPassword()));
        if (user.getPasswordDefault().equals(1)) {
            user.setPasswordDefault(0);
        }
        if (userMapper.updateByPrimaryKeySelective(user) <= 0) {
            return false;
        }
        return true;

    }

    @Override
    public void logout() {
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            throw new UserException(StatusCode.FORBIDDEN);
        }
        //清掉onesignalID
        UserOneSignalExample userOneSignalExample = new UserOneSignalExample();
        userOneSignalExample.createCriteria().andUserIdEqualTo(info.getUser().getId());
        userOneSignalMapper.deleteByExample(userOneSignalExample);
        UserInfo u = info.getUser();
        if (u.getId() == null || u.getId().intValue() <= 0) {
            throw new UserException(StatusCode.FORBIDDEN);
        }

        rwRedisService.delete(info.getToken());
        // 清除用户的UniqueCode(set UniqueCode = null)
        recordDeviceMapper.clearUniqueCode(u.getId(), Instant.now().getEpochSecond());
    }
    @Override
    public List<UserPointInfo> getUserInfoFromMongo(List<Long> ids) {
        List<UserPointInfo> upList = new ArrayList<>();
        if (ids != null && ids.size() > 0) {
            List<UserEntity> users = userDao.getUsersByIds(ids);
            for (UserEntity user : users) {
                UserPointInfo userPointInfo = new UserPointInfo();
                userPointInfo.setUserId(user.getId());
                userPointInfo.setPoint(user.getLoc().getCoordinates());
                userPointInfo.setAvatar(user.getAvatar());
                userPointInfo.setNickname(user.getNickname());
                userPointInfo.setAccount(user.getAccount());
                userPointInfo.setType(user.getType());
                upList.add(userPointInfo);
            }
        }

        return upList;
    }

    @Override
    @Deprecated
    public List<UserInfo> getAll() {
        return userMapper.getAll();
    }

    @Override
    public List<Object> findPartAroundPeopleImg(Double[] point, Integer sexType, int number) {
//		UserInfo loginedUser = GlobalController.getNowUser();// 获取当前用户
//		BasicDBObject obQuery = new BasicDBObject();
//		obQuery.append("_id", new BasicDBObject("$ne", loginedUser.getId()));
//		if (sexType != null && sexType != 1) {
//			if (sexType == 2) {
//				obQuery.append("sex", ConstantValue.SEX_MAN);
//			} else if (sexType == 3) {
//				obQuery.append("sex", ConstantValue.SEX_WOMAN);
//			} else if (sexType == 4) {
//				obQuery.append("sex", ConstantValue.SEX_UNKNOW);
//			}
//
//		}
//		// 隐私设置
//		List<Object> friendsList = rwRedisService.opsForListRead()
//				.range(RedisKey.USER_FRIENDS_REDIS_KEY + loginedUser.getId(), 0, -1);
//		List<BasicDBObject> serectSearchList = new ArrayList<>();
//		BasicDBObject serectZero = new BasicDBObject("secret", 0);
//		BasicDBObject serectOne = new BasicDBObject("secret", 1);
//		serectOne.append("_id", new BasicDBObject("$in", friendsList));
//		serectSearchList.add(serectZero);
//		serectSearchList.add(serectOne);
//		obQuery.put("$or", serectSearchList);
//		List<BasicDBObject> pipeline = new ArrayList<>();
//		BasicDBObject projectObject = new BasicDBObject("$project", new BasicDBObject("ava", "$avatar"));
//		pipeline.add(projectObject);
//		BasicDBObject sampleObject = new BasicDBObject("$sample", new BasicDBObject("size", number));
//		pipeline.add(sampleObject);
//		/*
//		 * BasicDBObject limitObject = new
//		 * BasicDBObject("$limit",ConstantValue.RANDOM_SHOW_LIMIT);
//		 * pipeline.add(limitObject);
//		 */
//		AggregateIterable<Document> iterators = userDao.findAroundPeople(ConstantValue.COLLECTION_USER, point,
//				ConstantValue.SEARCH_MAXDISTANCE, obQuery, pipeline);
//		// 更新坐标
//		// BasicDBObject filter = new BasicDBObject("_id",loginedUser.getId());
//		// Document update = new Document("loc.coordinates", Arrays.asList(point));
//		Query query = Query.query(Criteria.where("_id").is(loginedUser.getId()));
//		Update update = new Update().set("loc.coordinates", Arrays.asList(point));
//		userDao.updateUserInfo(query, update);
//
//		List<Object> resultList = new ArrayList<>();
//		MongoCursor<Document> cursor = iterators.iterator();
//		while (cursor.hasNext()) {
//			resultList.add(cursor.next().getString("ava"));
//		}
//		List<AdvInfo> list = new ArrayList<>();
//		resultList.add(3, list.get(1));
//		return resultList;
        return new ArrayList<>();
    }

    @Override
    public List<Long> findPartAroundPeopleImgV2(Double[] point, Integer sexType, int number) {
        UserInfo loginedUser = GlobalController.getNowUser();// 获取当前用户
        BasicDBObject obQuery = new BasicDBObject();
        obQuery.append("_id", new BasicDBObject("$ne", loginedUser.getId()));
        if (sexType != null && sexType != 1) {
            if (sexType == 2) {
                obQuery.append("sex", ConstantValue.SEX_MAN);
            } else if (sexType == 3) {
                obQuery.append("sex", ConstantValue.SEX_WOMAN);
            } else if (sexType == 4) {
                obQuery.append("sex", ConstantValue.SEX_UNKNOW);
            }

        }
        // 隐私设置
        List<Object> friendsList = rwRedisService.opsForListRead()
                .range(RedisKey.USER_FRIENDS_REDIS_KEY + loginedUser.getId(), 0, -1);
        List<BasicDBObject> serectSearchList = new ArrayList<>();
        BasicDBObject serectZero = new BasicDBObject("secret", 0);
        BasicDBObject serectOne = new BasicDBObject("secret", 1);
        serectOne.append("_id", new BasicDBObject("$in", friendsList));
        serectSearchList.add(serectZero);
        serectSearchList.add(serectOne);
        obQuery.put("$or", serectSearchList);
        List<BasicDBObject> pipeline = new ArrayList<>();
        BasicDBObject projectObject = new BasicDBObject("$project", new BasicDBObject("_id", 1));
        pipeline.add(projectObject);
        BasicDBObject sampleObject = new BasicDBObject("$sample", new BasicDBObject("size", number));
        pipeline.add(sampleObject);
        AggregateIterable<Document> iterators = userDao.findAroundPeople(ConstantValue.COLLECTION_USER, point,
                ConstantValue.SEARCH_MAXDISTANCE, obQuery, pipeline);
        Query query = Query.query(Criteria.where("_id").is(loginedUser.getId()));
        Update update = new Update().set("loc.coordinates", Arrays.asList(point));
        userDao.updateUserInfo(query, update);
        List<Long> resultList = new ArrayList<>();
        MongoCursor<Document> cursor = iterators.iterator();
        while (cursor.hasNext()) {
            resultList.add(cursor.next().getLong("_id"));
        }
        return resultList;
    }

    private void findAroundPeopleSexType(Integer sexType, BasicDBObject obQuery) {
        if (sexType != null && sexType != 1) {
            if (sexType == 2) {
                obQuery.append("sex", ConstantValue.SEX_MAN);
            } else if (sexType == 3) {
                obQuery.append("sex", ConstantValue.SEX_WOMAN);
            } else if (sexType == 4) {
                obQuery.append("sex", ConstantValue.SEX_UNKNOW);
            }
        }
    }

    private void findAroundPeopleLoginTime(Integer showtimeType, BasicDBObject obQuery, long currenttime) {
        long loginTime = 0L;
        if (null != showtimeType && 1 != showtimeType) {
            if (showtimeType == 2) {
                loginTime = 3600L;// 1小时
            } else if (showtimeType == 3) {
                loginTime = 3600L * 6; // 6小时
            } else if (showtimeType == 4) {
//                loginTime = currenttime; // 三小时=所有用户
                loginTime = 3600L * 24; //24小时
            }
            obQuery.append("loginTime", new BasicDBObject("$gte", currenttime - loginTime));
        }
    }

    private void findAroundPeopleAge(Integer leastAge, Integer largetAge, BasicDBObject obQuery, long currenttime) {
        long starttime = 0L;
        if (null == leastAge) {
            starttime = ConstantValue.LEAST_AGE * ConstantValue.YEAR_MILLIS;
        } else {
            starttime = leastAge * ConstantValue.YEAR_MILLIS;
        }
        BasicDBObject birthday = new BasicDBObject("$lte", currenttime - starttime);
        if (null != largetAge && largetAge < 80) {
            long endtime = currenttime - (largetAge + 1) * ConstantValue.YEAR_MILLIS;
            birthday.put("$gte", endtime);
        }
        obQuery.put("birthday", birthday);
    }

    private void findAroundPeopleSecret(long userId, BasicDBObject obQuery) {
        List<Object> friendsList = rwRedisService.opsForListRead().range(RedisKey.USER_FRIENDS_REDIS_KEY + userId, 0,
                -1);
        List<BasicDBObject> serectSearchList = new ArrayList<>();
        BasicDBObject serectZero = new BasicDBObject("secret", 0);
        BasicDBObject serectOne = new BasicDBObject("secret", 1);
        serectOne.append("_id", new BasicDBObject("$in", friendsList));
        serectSearchList.add(serectZero);
        serectSearchList.add(serectOne);
        obQuery.put("$or", serectSearchList);
    }

    private List<BasicDBObject> findAroundPeoplePipeline(Integer page, Integer pageCount, long currenttime) {
        if (null == page || page <= 0) {
            page = 1;
        }
        List<BasicDBObject> pipeline = new ArrayList<>();
        List<Object> birdiv = new ArrayList<>();
        List<Object> birsub = new ArrayList<>();
        List<Object> logindiv = new ArrayList<>();
        List<Object> loginsub = new ArrayList<>();
        birsub.add(currenttime);
        birsub.add("$birthday");
        birdiv.add(new BasicDBObject("$subtract", birsub));
        birdiv.add(ConstantValue.YEAR_MILLIS);
        loginsub.add(currenttime);
        loginsub.add("$loginTime");
        logindiv.add(new BasicDBObject("$subtract", loginsub));
        logindiv.add(ConstantValue.MINUTE_MILLIS);
        BasicDBObject projectObject = new BasicDBObject("$project",
                new BasicDBObject("_id", 1).append("sex", 1).append("nic", "$nickname").append("ava", "$avatar")
                        .append("sign", 1).append("dis", new BasicDBObject("$trunc", "$distance"))
                        .append("bir", new BasicDBObject("$trunc", new BasicDBObject("$divide", birdiv)))
                        .append("log", "$loginTime").append("type", "$type"));
        pipeline.add(projectObject);
        if (pageCount == null || pageCount <= 0 || pageCount > ConstantValue.SHOW_LIMIT) {
            pageCount = ConstantValue.SHOW_LIMIT;
        }
        BasicDBObject skipObject = new BasicDBObject("$skip", (page - 1) * pageCount);
        pipeline.add(skipObject);
        BasicDBObject limitObject = new BasicDBObject("$limit", pageCount);
        pipeline.add(limitObject);
        BasicDBObject sortObject = new BasicDBObject("$sort", new BasicDBObject("distance", 1).append("loginTime", -1));
        pipeline.add(sortObject);
        return pipeline;
    }

    private AroundPersonInfo findAroundPeopleObjectConvert(Document doc) {
        AroundPersonInfo tempObj = new AroundPersonInfo();
        tempObj.setId(doc.getLong("_id"));
        tempObj.setNickname(doc.getString("nic"));
        tempObj.setSex(doc.getString("sex"));
        tempObj.setAge(doc.getDouble("bir"));
        tempObj.setLastloginTime(doc.getLong("log"));
        tempObj.setDistance(doc.getDouble("dis"));
        tempObj.setImg(doc.getString("ava"));
        tempObj.setSign(doc.getString("sign"));
        tempObj.setVip(doc.containsKey("vip")? doc.getInteger("vip") : 0);
        Object type = doc.get("type");
        if (type instanceof Double) {
            tempObj.setType(((Double) type).intValue());
        } else {
            tempObj.setType((Integer) type);
        }
        tempObj.setDis(DistanceHandleUtil.convertDoubleToStringFormat(doc.getDouble("dis")));
        return tempObj;
    }

    @Override
    public List<AroundPersonInfo> findAroundPeople(Double[] point, Integer page, Integer distance, Integer sexType,
                                                   Integer showtimeType, Integer leastAge, Integer largetAge, Integer pageCount, AdvNearbyDto advNearbyDto) {
        UserInfo loginedUser = GlobalController.getNowUserNoCheck();
        BasicDBObject obQuery = new BasicDBObject();
        // 过滤自身id
        if(loginedUser!=null)
        obQuery.put("_id", new BasicDBObject("$ne", loginedUser.getId()));
        // 过滤未完善信息用户（头像、昵称、性别非空）
//        obQuery.append("avatar", new BasicDBObject("$ne", null));
        obQuery.append("nickname", new BasicDBObject("$ne", null));
        obQuery.append("sex", new BasicDBObject("$ne", null));
        obQuery.append("version", new BasicDBObject("$ne", null));
        obQuery.append("type", 1);
        if(GlobalController.getNowUser().getHonoured()==null || !GlobalController.getNowUser().getHonoured() ){//不是VIP
            obQuery.append("vip", new BasicDBObject("$in", new Integer[]{null,0}));
        }else {
            obQuery.append("vip",1);
        }
        float a = 1f;
        long currenttime = System.currentTimeMillis() / 1000; // 当前秒数
        // 性别
        findAroundPeopleSexType(sexType, obQuery);
        // 登录时间
        findAroundPeopleLoginTime(showtimeType, obQuery, currenttime);
        // 年龄条件
        findAroundPeopleAge(leastAge, largetAge, obQuery, currenttime);
        // 隐私设置
        if(loginedUser!=null)
        findAroundPeopleSecret(loginedUser.getId(), obQuery);

        if (distance != null && distance > 0 && distance < 100) {
            distance = ConstantValue.KM_TO_M_COEFFICIENT * distance;
        } else {
            distance = ConstantValue.SEARCH_MAXDISTANCE;
        }

        AggregateIterable<Document> iterators = userDao.findAroundPeople(ConstantValue.COLLECTION_USER, point, distance,
                obQuery, findAroundPeoplePipeline(page, pageCount, currenttime));
        List<AroundPersonInfo> resultList = new ArrayList<>();
        MongoCursor<Document> cursor = iterators.iterator();
        while (cursor.hasNext()) {
            resultList.add(findAroundPeopleObjectConvert(cursor.next()));
        }
        if(loginedUser!=null)
        advNearbyDto.setAge(((currenttime - loginedUser.getBirthday()) / ConstantValue.YEAR_MILLIS));
        else
            advNearbyDto.setAge(18L);
        advNearbyDto.setNumber(2);
        if(loginedUser!=null)
        advNearbyDto.setSex(loginedUser.getSex());
        else
            advNearbyDto.setSex("M");
        findAroundPeopleAdv(advNearbyDto, resultList);
        return resultList;
    }
    @Override
    public List<ModelPersonInfo> findModle(int page, int limit) {
        int pageStart = (page - 1) * limit;
        List<ModelPersonInfo> modelInfos = new ArrayList<>();
        List<User> userList = userMapper.findModel(pageStart ,limit);
        for (User user : userList){
            ModelPersonInfo modelInfo = JSONObject.parseObject(JSONObject.toJSONString(user),ModelPersonInfo.class);
            modelInfo.setImg(user.getAvatar());
            try {
                modelInfo.setAge(getAgeByBirth(new Date(user.getBirthday() * 1000L)));
                modelInfo.setCity(user.getCityName());
            } catch (ParseException e) {
                e.printStackTrace();
            }
            modelInfos.add(modelInfo);
        }
        return modelInfos;

    }

    /**
     * 时间转年龄
     * @param birthDay
     * @return
     * @throws ParseException
     */
    public static int getAgeByBirth(Date birthDay) throws ParseException {
        int age = 0;
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) { //出生日期晚于当前时间，无法计算
            throw new IllegalArgumentException(
                    "The birthDay is before Now.It's unbelievable!");
        }
        int yearNow = cal.get(Calendar.YEAR);  //当前年份
        int monthNow = cal.get(Calendar.MONTH);  //当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        age = yearNow - yearBirth;   //计算整岁数
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) age--;//当前日期在生日之前，年龄减一
            } else {
                age--;//当前月份在生日之前，年龄减一
            }
        }
        return age;
    }
    private void findAroundPeopleAdv(AdvNearbyDto advNearbyDto, List<AroundPersonInfo> resultList) {
        ResponseEntity<Response> res = advFeignService.getNearbyVideoInfo(advNearbyDto);
        if (BasicResponseHandle.convertListObject(res)) {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            List<AroundPersonAdvInfo> advlist = objectMapper.convertValue(res.getBody().getData(),
                    new TypeReference<List<AroundPersonAdvInfo>>() {
                    });
            int advSize = advlist.size();
            if (advSize > 0) {
                int size = resultList.size();
                int addNumber = size + advSize - ConstantValue.SHOW_LIMIT;
                if (addNumber > 0) {
                    for (; addNumber > 0; addNumber--) {
                        size--;
                        resultList.remove((int) Math.round(Math.random() * size));
                    }
                    if (advSize == 2) {
                        resultList.add((int) Math.round(Math.random() * size), advlist.get(0));
                        resultList.add((int) Math.round(Math.random() * size), advlist.get(1));
                    } else if (advSize == 1) {
                        resultList.add((int) Math.round(Math.random() * size), advlist.get(0));
                    }
                }
            }
        }
    }

    private void userPointInfo(long userId, Double[] point) {
        Query query = Query.query(Criteria.where("_id").is(userId));
        Update update = new Update().set("loc.coordinates", Arrays.asList(point));
        userDao.updateUserInfo(query, update);
    }

    @Override
    public Map<String, Object> getUserInfoNum(Long id) {
        if (id == null || id.intValue() <= 0) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        // 好友数
        Integer friendsNum = 0;
        String friendsKey = "friends_key_" + id;
        if (rwRedisService.hasKey(friendsKey)) {
            List<Object> list = rwRedisService.lrange(friendsKey, 0, -1);
            friendsNum = list.size();
        } else {
            friendsNum = userMapper.selectFriendsNum(id);
        }
        // 关注数
        Integer followNum = 0;
        followNum = userMapper.selectFollowNum(id);
        // 粉丝数
        Integer fansNum = userMapper.selectFansNum(id);
        // 群数
        Integer groupNum = userMapper.selectGroupNum(id);
        HashMap<String, Object> hashMap = new HashMap<String, Object>();
        hashMap.put("friendsNum", friendsNum);
        hashMap.put("followNum", followNum);
        hashMap.put("fansNum", fansNum);
        hashMap.put("groupNum", groupNum);

        VipInfo vipInfo = vipService.getVipInfo(id);
        hashMap.put("vip", vipInfo.isVip());
        hashMap.put("vipEndTime", vipInfo.getEndTime());
        return hashMap;
    }

    @Override
    public Long newTipOff(TipOffDto dto) {
        UserInfo u = GlobalController.getNowUser();
        TipOffDto tipOffDto = new TipOffDto();
        tipOffDto.setImg1(dto.getImg1());
        tipOffDto.setImg2(dto.getImg2());
        tipOffDto.setImg3(dto.getImg3());
        tipOffDto.setMark(dto.getMark());
        tipOffDto.setStatus(0);
        tipOffDto.setTarget_id(dto.getTarget_id());
        tipOffDto.setType(dto.getType());
        long nowMilliSeconds = System.currentTimeMillis();
        long nowSeconds = nowMilliSeconds / 1000;
        tipOffDto.setCreated_time(nowSeconds);
        tipOffDto.setUser_id(u.getId());
        long id = userMapper.insertTipOff(tipOffDto);
        return id;
    }

    @Override
    public Integer getRegionId(GetReginIdDto getReginIdDto) {
        Integer id = userMapper.getRegionId(getReginIdDto.getPhonetype(), getReginIdDto.getLanguage(),
                getReginIdDto.getRegionname());
        return id;
    }

    @Override
    public boolean checktoken(String token) {
        if (StringUtils.isBlank(token)) {
            return false;
        }
        if (!rwRedisService.hasKey(token)) {
            return false;
        }
        rwRedisService.expire(token, 25200L);
        LocalUserInfo user = (LocalUserInfo) rwRedisService.getThroughWrite(token);
        LocalUser.setUser(user);
        return true;
    }

    /*-------------------*/
    @Override
    public boolean bindface(String facebookID) {
        // 参数验证
        Preconditions.checkArgument(!StringUtils.isEmpty(facebookID), StatusCode.BAD_REQUEST.msg());
        // 用户验证
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserInfo u = info.getUser();
        if (u.getId() == null || u.getId().intValue() <= 0) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        User user = userMapper.selectByPrimaryKey(u.getId());
        if (user == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        // 检测类型是否已经被绑定
        User us = new User();
        us.setFacebookOpenId(facebookID);
        if (userMapper.selectCount(us) != 0) {
            throw new UserException(StatusCode.ACCOUNT_EXIST);
        }
        ;
        // 未绑定 绑定用户信息 先按照类型注值
        user.setFacebookOpenId(facebookID);
        // 更新MySQL用户信息
        if (userMapper.updateByPrimaryKeySelective(user) <= 0) {
            throw new UserException(StatusCode.USER_UPDATE_FAILED);
        }
        // 更新用户token
        UserInfo ui = ConvertUtil.UserToUserInfo(user);
        info.setUser(ui);
        tokenManagerService.updateUser(info);

        rwRedisService.opsForHash().delete(user_key, ui.getId());
        return true;
    }

    @Override
    public boolean bind(Integer type, String flag, String code) {
        // 参数非空验证
        Preconditions.checkArgument(!StringUtils.isEmpty(flag), StatusCode.BAD_REQUEST.msg());
        Preconditions.checkArgument(!StringUtils.isEmpty(code), StatusCode.BAD_REQUEST.msg());
        // 用户验证
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserInfo u = info.getUser();
        if (u.getId() == null || u.getId().intValue() <= 0) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        User user = userMapper.selectByPrimaryKey(u.getId());
        if (user == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        // 是否已经被绑定
        if (!accountExist(flag, type)) {
            throw new UserException(StatusCode.ACCOUNT_EXIST);
        }
        // 判断是哪种绑定
        if (type.intValue() == 1) {
            // 校验手机验证码
            String countryCode = verificationCodeService.checkSmsCodeAndGetCountryCode(flag, code, 4);// verificationCodeService.checkSmsCode(flag,
            // code, 4);
            user.setMobilephone(flag);
            user.setCountryCode(countryCode);
        } else if (type.intValue() == 3) {
            // 校验邮箱验证码
            verificationCodeService.checkSmsCode(flag, code, 5);
            user.setEmail(flag);
        }
        // 更新MySQL用户信息
        if (userMapper.updateByPrimaryKeySelective(user) <= 0) {
            throw new UserException(StatusCode.USER_UPDATE_FAILED);
        }
        // 更新用户token
        UserInfo ui = ConvertUtil.UserToUserInfo(user);

        /*
         * 异步操作 RocketMqUtil.send(MqTag.ROCKETMQ_BEAN_USEREDITTOSOLR, ui, MqTag.SEARCH);
         */

        info.setUser(ui);
        tokenManagerService.updateUser(info);
        // 更新Redis缓存用户信息
        rwRedisService.opsForHash().delete(user_key, u.getId());
        return true;
    }

    @Override
    public boolean setSecretLevel(UserInfoDto dto) {
        if (dto.getSecret() == null) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        if (dto.getSecret() >= 0 && dto.getSecret() <= 2) {
            return updateUserInfo(dto);
        }
        throw new UserException(StatusCode.BAD_REQUEST);
    }

    @Override
    public boolean setNotifyLevel(UserNotifyDto dto) {
        // 用户验证
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserInfo u = info.getUser();
        if (u.getId() == null || u.getId().intValue() <= 0) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        User user = userMapper.selectByPrimaryKey(u.getId());
        if (user == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        // 参数检验
        ConvertUtil.check(dto);
        // 更改MySQL
        user.setNotifyZan(dto.getNotifyZan());
        user.setNotifyComment(dto.getNotifyComment());
        user.setNotifyFollow(dto.getNotifyFollow());
        user.setNotifyGroup(dto.getNotifyGroup());
        user.setNotifyVoice(dto.getNotifyVoice());
        if (userMapper.updateByPrimaryKeySelective(user) <= 0) {
            throw new UserException(StatusCode.USER_UPDATE_FAILED);
        }
        // 更新用户token
        UserInfo ui = ConvertUtil.UserToUserInfo(user);
        info.setUser(ui);
        tokenManagerService.updateUser(info);
        rwRedisService.opsForHash().delete(user_key, u.getId());
        return true;
    }

    @Override
    public boolean unBind(Integer type) {
        // 用户验证
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserInfo u = info.getUser();
        if (u.getId() == null || u.getId().intValue() <= 0) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        User user = userMapper.selectByPrimaryKey(u.getId());
        if (user == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        logger.info("解绑类型    ", type.toString());
        logger.info("需要解绑的用户信息是    ", user);
        if (type.intValue() == 1) {
            user.setMobilephone(null);
        } else if (type.intValue() == 2) {
            user.setEmail(null);
        } else if (type.intValue() == 3) {
            if (user.getMobilephone() == null) {
                throw new UserException(StatusCode.MOBILEPHONE_NOT_EXIST);
            }
            user.setFacebookOpenId(null);
        } else {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        if (userMapper.updateByPrimaryKey(user) <= 0) {
            throw new UserException(StatusCode.USER_UPDATE_FAILED);
        }
        UserInfo ui = ConvertUtil.UserToUserInfo(user);
        info.setUser(ui);
        logger.info("token中的info是   ", info);
        tokenManagerService.updateUser(info);
        logger.info("redis中的info是   ", ui);
        rwRedisService.opsForHash().delete(user_key, u.getId());
        return true;
    }

    @Override
    public UserAreaInfo getAreaInfo(String lang, Long id) {
        UserInfo ui = this.getUserInfoById(id);
        UserAraeDto dto = new UserAraeDto();
        dto.setCity(ui.getHomeCity());
        dto.setPri(ui.getHomeProvince());
        dto.setCountry(ui.getHomeCountry());
        dto.setLang(lang);
        ResponseEntity<Response> res = userAreaInfoService.getArea(dto);
        if (res.getStatusCodeValue() != 200) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        if (res.getBody() == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        if (res.getBody().getMeta().getCode() != 200) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        Object o = res.getBody().getData();
        if (o == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        ObjectMapper x = new ObjectMapper();
        UserAreaInfo userAreaInfo = x.convertValue(o, UserAreaInfo.class);
        logger.info(userAreaInfo.getCityName() + "-----" + userAreaInfo.getCountryName() + "-----"
                + userAreaInfo.getProvinceName());
        return userAreaInfo;
    }

    @Override
    public List<Long> getfollowedByUserId(Long userId, List<Long> ids) {
        return userMapper.getfollowedByUserId(userId, ids);
    }

    @Override
    public String getUserCountryCode() {
        UserInfo loginedUser = GlobalController.getNowUser();
        return userMapper.getUserCountryCodeById(loginedUser.getId());
    }

    @Override
    public boolean updateUserSex(SexDto dto) {
        if (dto.getSex() == null || StringUtils.isEmpty(dto.getSex())) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        UserInfo u = info.getUser();
        if (u.getId() == null || u.getId().intValue() <= 0) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
        User user = userMapper.selectByPrimaryKey(u.getId());
        if (user == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        }
///   去除性别修改次数的限制
//		if (user.getSexModified().equals(1)) {
//			return false;
//		}
        user.setSex(dto.getSex());
        user.setSexModified(1);
        long nowMilliSeconds = System.currentTimeMillis() / 1000;
        user.setUpdatedTime(nowMilliSeconds);
        if (userMapper.updateByPrimaryKeySelective(user) <= 0) {
            throw new UserException(StatusCode.USER_UPDATE_FAILED);
        }
        Query query = Query.query(Criteria.where("_id").is(u.getId()));
        Update update = new Update().set("sex", dto.getSex());
        userDao.updateUserInfo(query, update);
        u.setSex(dto.getSex());
        u.setSexModified(1);
        info.setUser(u);

        /*
         * 异步处理 RocketMqUtil.send(MqTag.ROCKETMQ_BEAN_USERTOSOLR, u, MqTag.SEARCH);
         */

        tokenManagerService.updateUser(info);
        UserInfo tempInfo = (UserInfo) rwRedisService.hget(user_key, u.getId());
        if (tempInfo != null) {
            u.setDevice(tempInfo.getDevice());
        }
        rwRedisService.opsForHash().delete(user_key, u.getId());
        return true;
    }

    @Override
    public boolean updateUserPoint(List<Double> point, long userId) {
        if (point.get(0) != 0 && point.get(1) != 0) {
            Query query = Query.query(Criteria.where("_id").is(userId));
            Update update = new Update().set("loc.coordinates", point);
            userDao.updateUserInfo(query, update);
        } else {
            // 都等于0，先去看看之前的经纬度 如果还是0 则更新成30334用户的经纬度
            UserEntity user = userDao.getUserById(userId);
            Double[] coordinates = user.getLoc().getCoordinates();
            if (ArrayUtils.isEmpty(coordinates) || coordinates.length != 2) {
                coordinates = new Double[]{0.0, 0.0};
            }
            ;
            if (coordinates[0] == 0 && coordinates[1] == 0) {
                user = userDao.getUserById(30334L);
                coordinates = user.getLoc().getCoordinates();
                point = Arrays.asList(coordinates);
                Query query = Query.query(Criteria.where("_id").is(userId));
                Update update = new Update().set("loc.coordinates", point);
                userDao.updateUserInfo(query, update);
            }
        }
        return true;
    }

    @Override
    public List<BlackUserInfo> getBlackList(Integer page, Integer size) {
        List<BlackUserInfo> bulist = new ArrayList<BlackUserInfo>();
        page = GlobalController.checkPage(page, size);
        UserInfo userInfo = GlobalController.getNowUser();
        Long id = userInfo.getId();
        // 获得举报id
        Long tipoff = (long) ((page - 1) * size);
        List<Black> list = blackmapper.findBlackListById(id, tipoff, size);
        if (list.size() == 0) {
            return bulist;
        }
        List<Long> idlist = ConvertUtil.BlackToBlackUserInfo(list);
        List<User> userlist = userMapper.findByIdList(idlist);
        for (Black black : list) {
            for (User user : userlist) {
                if (black.getBlackUserId().equals(user.getId())) {
                    BlackUserInfo bl = new BlackUserInfo(black.getBlackUserId(), user.getAvatar(), user.getNickname(),
                            black.getCreateTime());
                    bulist.add(bl);
                }
            }
        }
        return bulist;
    }

    @Override
    public Boolean blackUser(Long userId) {
        Long time = System.currentTimeMillis() / 1000;
        UserInfo userInfo = GlobalController.getNowUser();
        Long id = userInfo.getId();
        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        Black record = new Black();
        record.setUserId(id);
        record.setBlackUserId(userId);
        Black black = blackmapper.findById(id, userId);
        if (black != null) {
            if (black.getStatus() == 1) {
                throw new UserException(StatusCode.ACCOUNT_ISBLACK);
            } else {
                black.setStatus(1);
                black.setUpdateTime(time);
                if (blackmapper.updateStatus(black.getId(), time, 1) != 1) {
                    throw new UserException(StatusCode.INTERNAL_SERVER_ERROR);
                }
            }
        } else {
            record.setStatus(1);
            record.setCreateTime(time);
            record.setUpdateTime(time);
            if (blackmapper.insert(record) != 1) {
                throw new UserException(StatusCode.INTERNAL_SERVER_ERROR);
            }
        }
        return true;
    }

    @Override
    public Boolean cancelBlackUser(Long userId) {
        Long time = System.currentTimeMillis() / 1000;
        UserInfo userInfo = GlobalController.getNowUser();
        Long id = userInfo.getId();
        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        Black black = blackmapper.findById(id, userId);
        if (black == null) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        if (black.getStatus() == 0) {
            throw new UserException(StatusCode.BAD_REQUEST);
        }
        black.setUpdateTime(time);
        if (blackmapper.updateStatus(black.getId(), time, 0) != 1) {
            throw new UserException(StatusCode.INTERNAL_SERVER_ERROR);
        }
        return true;
    }

    @Override
    public UserInfo getWatermarkVideoUserInfo(Long id) {
        UserInfo userInfo = (UserInfo) rwRedisService.hget(user_key, id);
        if (null == userInfo) {
            User mysqlUser = userMapper.selectByPrimaryKey(id);
            if (mysqlUser == null) {
                throw new UserException(StatusCode.USER_EXCEPTION);
            }
            userInfo = ConvertUtil.UserToUserInfo(mysqlUser);
            // 存缓存
            rwRedisService.opsForHash().delete(user_key, userInfo.getId());
        }
        return userInfo;
    }

    @Override
    public boolean updateLastLoginTime() {
        LocalUserInfo info = LocalUser.getUser();
        if (info == null) {
            logger.error("");
            // throw new UserException(StatusCode.USER_EXCEPTION);
            return false;
        }
        UserInfo u = info.getUser();
        if (u.getId() == null || u.getId().intValue() <= 0) {
            logger.error("");
            // throw new UserException(StatusCode.USER_EXCEPTION);
            return false;
        }
        long nowSeconds = System.currentTimeMillis() / 1000;
        // 更新redis
        u.setLastLoginTime(nowSeconds);
        info.setUser(u);
        rwRedisService.set(info.getToken(), info);

        if(userDao.getUserById(u.getId()) == null){//更新用户 mongo信息
            UserEntity entity = new UserEntity();
            User user = userMapper.findByAccount(u.getAccount());
            entity.setAccount(user.getAccount());
            entity.setAvatar(user.getAvatar());
            entity.setAvatarSmall(user.getAvatarSmall());
            entity.setBirthday(user.getBirthday());
            entity.setCelebrity(user.getCelebrity());
            entity.setChecked(0);
            entity.setDevice(null);
            entity.setFirstImg(userPhotosMapper.getListByUid(u.getId()).get(0).getPhoto());
            entity.setId(user.getId());
            entity.setJob(user.getJob());
            entity.setSex(user.getSex());
            Loc loc = new Loc();
            loc.setType("Point");
            int i = (int) Math.round(Math.random() * 6);
            double lng = pointArray[i][1] + Math.random() / 10;
            double lat = pointArray[i][0] + Math.random() / 10;
            Double[] point = {lng, lat};
            loc.setCoordinates(point);
            entity.setLoc(loc);
            entity.setVerified(user.getVerified());
            entity.setNickname(user.getNickname());
            entity.setOnline(1);
            entity.setOpenT(user.getOpenT());
            entity.setLoginTime(nowSeconds);
            entity.setType(user.getType());
            entity.setSign(user.getSign() );

//            entity.setPlatform();
            entity.setVip(vipService.isVip(user.getId()) ? 1 :0);
            entity.setSecret(user.getSecret());
            userDao.saveUser(entity);
        }
        // 更新mogon
        UserEntity user = new UserEntity();
        user.setId(u.getId());
        user.setLoginTime(nowSeconds);
        userDao.updateLastLoginTime(user);
        return true;
    }
    @Override
    public VideoUserInfo getVideoUserInfoById(Long id) {
        VideoUserInfo result = userMapper.getVideoUserInfoById(id);
        return result;
    }

    @Override
    public String getUserDevice(long id) {
        return userDao.getUserById(id).getDevice();
    }

    double[][] pointArray = {{39.9097728, 116.4001922}, {31.2175452, 121.5006593}, {23.0595119, 113.2800127},
            {22.5664787, 114.0600688}, {32.0406959, 118.7951800}, {30.2768733, 120.1705295},
            {30.6556517, 104.0707535}, {29.5531531, 106.5378512}, {30.5332596, 114.3030931},
            {31.3160952, 120.6092581}, {31.5758960, 120.3023402}};
    @Autowired
    UserRepository userRepository;

    @Override
    public boolean syncMongoData(Long startId, Long endId) {
        Example query = new Example(User.class);
        query.createCriteria().andBetween("id", startId, endId);
        List<User> userList = userMapper.selectByExample(query);
        logger.info("startId:{},endId{},mysql中查询出{}个", startId, endId, userList == null ? 0 : userList.size());
        List<MyUserEntity> userDBList = new ArrayList<>();
        long id = 80000;
        for (User obj : userList) {
            MyUserEntity doc = new MyUserEntity();
            BeanUtils.copyProperties(obj, doc);

            doc.setLoginTime(System.currentTimeMillis() / 1000);
            doc.setPlatform("android 9");
            doc.setOnline(0);
//			doc.put("version", "2.0.1");
            doc.setDevice("1+");
            Loc loc = new Loc();
            loc.setType("Point");
            int i = (int) Math.round(Math.random() * 6);
            double lng = pointArray[i][1] + Math.random() / 10;
            double lat = pointArray[i][0] + Math.random() / 10;
            Double[] point = {lng, lat};
            loc.setCoordinates(point);
            doc.setLoc(loc);
            userDBList.add(doc);
        }
//		List<MyUserEntity> rs = userRepository.findAll();
//		System.out.println(JSONObject.toJSONString(rs));
        List<MyUserEntity> rr = userRepository.saveAll(userDBList);
//		writeMongoTemplate.getCollection("userEntity").insertMany(userDBList);
        return true;
    }

    @Override
    public List<Long> findTantanPartAroundPeopleImg(Double[] point, Integer sexType) {
        UserInfo loginedUser = GlobalController.getNowUser();// 获取当前用户
        BasicDBObject obQuery = new BasicDBObject();
        obQuery.append("_id", new BasicDBObject("$ne", loginedUser.getId()));
        // obQuery.append("openT", 1);//是否开启探探功能 (1,无需关心用户是否开启该功能)
        if (sexType != null && sexType != 1) {
            if (sexType == 2) {
                obQuery.append("sex", ConstantValue.SEX_MAN);
            } else if (sexType == 3) {
                obQuery.append("sex", ConstantValue.SEX_WOMAN);
            } else if (sexType == 4) {
                obQuery.append("sex", ConstantValue.SEX_UNKNOW);
            }
        }
        // 是否开启探探
        List<BasicDBObject> pipeline = new ArrayList<>();
        BasicDBObject projectObject = new BasicDBObject("$project", new BasicDBObject("_id", 1));
        pipeline.add(projectObject);
        BasicDBObject sampleObject = new BasicDBObject("$sample",
                new BasicDBObject("size", ConstantValue.V1_RANDOM_SHOW_LIMIT));
        pipeline.add(sampleObject);
        AggregateIterable<Document> iterators = userDao.findAroundPeople(ConstantValue.COLLECTION_USER, point,
                ConstantValue.SEARCH_MAXDISTANCE, obQuery, pipeline);
        // 更新坐标
        Query query = Query.query(Criteria.where("_id").is(loginedUser.getId()));
        Update update = new Update().set("loc.coordinates", Arrays.asList(point));
        userDao.updateUserInfo(query, update);
        List<Long> resultList = new ArrayList<>();
        MongoCursor<Document> cursor = iterators.iterator();
        while (cursor.hasNext()) {
            resultList.add(cursor.next().getLong("_id"));
        }
        return resultList;
    }

    @Override
    public boolean ExistUserImgCompression(Long startId, Long endId) {
        /*
         * List<UserAvatarInfo> userList =
         * userMapper.listUserBetweenStartIdAndEndId(startId,endId);
         * //List<KeyValueModel<Long,String>> userList =
         * userMapper.listUserBetweenStartIdAndEndId1(startId,endId); for(UserAvatarInfo
         * obj : userList) { String samllresult =
         * UploadImgUtil.uploadSingleImgByInputStream(ImgHandleUtil.
         * compressionImgByUrlToInputStream(PropertiesParameter.FASTDSF_SERVER_URL +
         * obj.getAvatar(), 100, 100)); //压缩图片
         * userMapper.updateUserSmallAvatar(obj.getId(),samllresult); }
         */
        while (startId <= endId) {
            CompressionAvatar(startId);
            startId++;
        }
        return true;
    }

    @Override
    public String getUserSmallAvatar(Long userId) {
        /*
         * KeyValueModel<String, String> avatar =
         * userMapper.findUserSmallAvatarById(userId); String byteResult = null; byte[]
         * result = null; ByteArrayOutputStream baos = new ByteArrayOutputStream();
         * StorageClient1 storageClient1 = null; ConnectionPool pool =
         * ConnectionPool.getConnectionPool(); storageClient1 = pool.checkout(2); try {
         * if (avatar.getValue() == null) { byte[] source =
         * storageClient1.download_file1(avatar.getId()); if(source != null) { baos =
         * ImgHandleUtil.compressionImgByUrlToInputStream(source,
         * ConstantValue.IMG_SIZE_100, ConstantValue.IMG_SIZE_100); // 压缩图片
         * //IOUtils.copy(bais, baos); result = baos.toByteArray(); String samllresult =
         * UploadImgUtil.uploadSingleImgByByteArray(result);
         * userMapper.updateUserSmallAvatar(userId, samllresult); Query query =
         * Query.query(Criteria.where("_id").is(userId)); Update update = new
         * Update().set("avatarSmall", samllresult); userDao.updateUserInfo(query,
         * update); }
         *
         * } else { byte[] source = storageClient1.download_file1(avatar.getValue());
         * InputStream inputStream = new ByteArrayInputStream(source); result =
         * readInputStream(inputStream); } logger.info("图片URL 长度为" + result.length);
         * pool.checkin(storageClient1); byteResult =
         * BaseEncoding.base64().encode(result); } catch (MalformedURLException e) {
         * logger.error("获取用户小头像失败:" + e); } catch (ProtocolException e) {
         * logger.error("获取用户小头像失败:" + e); } catch (IOException e) {
         * logger.error("获取用户小头像失败:" + e); } catch (MyException e) {
         * pool.drop(storageClient1); logger.error("图片资源获取失败:" + e); }
         */
        return "";
    }

    /*
     * private static byte[] readInputStream(InputStream inStream) throws
     * IOException { ByteArrayOutputStream outStream = new ByteArrayOutputStream();
     * byte[] buffer = new byte[10240]; int len = 0; while ((len =
     * inStream.read(buffer)) != -1) { outStream.write(buffer, 0, len); }
     * inStream.close(); return outStream.toByteArray(); }
     */
    @Override
    public synchronized void CompressionAvatar(Long id) {
    }
    /*
     * String avatar = userMapper.findUserAvatarById(id); if
     * (StringUtils.isNotEmpty(avatar)) { byte[] result = null;
     * ByteArrayOutputStream baos = new ByteArrayOutputStream(); StorageClient1
     * storageClient1 = null; ConnectionPool pool =
     * ConnectionPool.getConnectionPool(); storageClient1 = pool.checkout(1); byte[]
     * source; try { source = storageClient1.download_file1(avatar); if (source !=
     * null) { baos = ImgHandleUtil.compressionImgByUrlToInputStream(source,
     * ConstantValue.IMG_SIZE_100, ConstantValue.IMG_SIZE_100); // 压缩图片 result =
     * baos.toByteArray(); String samllresult =
     * UploadImgUtil.uploadSingleImgByByteArray(result);
     * userMapper.updateUserSmallAvatar(id, samllresult); Query query =
     * Query.query(Criteria.where("_id").is(id)); Update update = new
     * Update().set("avatarSmall", samllresult); userDao.updateUserInfo(query,
     * update); pool.checkin(storageClient1); } } catch (IOException e) {
     * e.printStackTrace(); logger.error("获取用户小头像失败:" + e); } catch (MyException e)
     * { e.printStackTrace(); logger.error("图片资源获取失败:" + e); } }
     *
     * }
     *
     * @Override public List<String> findPartAroundPeopleImgV3(Double[] point,
     * Integer sexType, int number) { UserInfo loginedUser =
     * GlobalController.getNowUser();// 获取当前用户 BasicDBObject obQuery = new
     * BasicDBObject("avatarSmall", new BasicDBObject("$ne", ""));
     * List<BasicDBObject> pipeline = new ArrayList<>(); BasicDBObject projectObject
     * = new BasicDBObject("$project", new BasicDBObject("ava", "$avatarSmall"));
     * pipeline.add(projectObject); BasicDBObject sampleObject = new
     * BasicDBObject("$sample", new BasicDBObject("size", number));
     * pipeline.add(sampleObject); AggregateIterable<Document> iterators =
     * userDao.findAroundPeople(ConstantValue.COLLECTION_USER, point,
     * ConstantValue.SEARCH_MAXDISTANCE, obQuery, pipeline); Query query =
     * Query.query(Criteria.where("_id").is(loginedUser.getId())); Update update =
     * new Update().set("loc.coordinates", Arrays.asList(point));
     * userDao.updateUserInfo(query, update);
     *
     * List<String> resultList = new ArrayList<>(); MongoCursor<Document> cursor =
     * iterators.iterator(); while (cursor.hasNext()) {
     * resultList.add(cursor.next().getString("ava")); } return resultList; }
     */

    @Override
    public List<String> findTantanPartAroundPeopleImgV3(Double[] point, Integer sexType) {
        UserInfo loginedUser = GlobalController.getNowUser();// 获取当前用户
        BasicDBObject obQuery = new BasicDBObject("avatarSmall", new BasicDBObject("$ne", ""));
        List<BasicDBObject> pipeline = new ArrayList<>();
        BasicDBObject projectObject = new BasicDBObject("$project", new BasicDBObject("ava", "$avatarSmall"));
        pipeline.add(projectObject);
        BasicDBObject sampleObject = new BasicDBObject("$sample",
                new BasicDBObject("size", ConstantValue.V1_RANDOM_SHOW_LIMIT));
        pipeline.add(sampleObject);
        AggregateIterable<Document> iterators = userDao.findAroundPeople(ConstantValue.COLLECTION_USER, point,
                ConstantValue.SEARCH_MAXDISTANCE, obQuery, pipeline);
        // 更新坐标
        Query query = Query.query(Criteria.where("_id").is(loginedUser.getId()));
        Update update = new Update().set("loc.coordinates", Arrays.asList(point));
        userDao.updateUserInfo(query, update);
        List<String> resultList = new ArrayList<>();
        MongoCursor<Document> cursor = iterators.iterator();
        while (cursor.hasNext()) {
            resultList.add(cursor.next().getString("ava"));
        }
        return resultList;
    }

    @Override
    public boolean syncMysqlToMongo(Long startId, Long endId) {
        List<UserEntity> userList = userMapper.findAllUser(startId, endId);
        for (UserEntity obj : userList) {

            Query query = Query.query(Criteria.where("_id").is(obj.getId()));
            Update update = new Update().set("avatarSmall", obj.getAvatarSmall()).set("nickname", obj.getNickname())
                    .set("sex", obj.getSex()).set("avatar", obj.getAvatar()).set("birthday", obj.getBirthday())
                    .set("vip", obj.getVip()).set("celebrity", obj.getCelebrity()).set("verified", obj.getVerified())
                    .set("sign", obj.getSign()).set("secret", obj.getSecret()).set("account", obj.getAccount())
                    .set("job", obj.getJob()).set("openT", obj.getOpenT());
            if (obj.getOpenT() == null || obj.getOpenT() == 0) {
                update.set("checked", 0);
                update.set("firstImg", "");
            } else {
                update.set("checked", obj.getChecked());
                update.set("firstImg", obj.getFirstImg());
            }
            userDao.updateUserInfo(query, update);
        }
        return true;
    }

    @Override
    public JSONObject loginById(LoginByIdDto loginDto) {
        User user = userMapper.selectByPrimaryKey(loginDto.getId());
        if (user == null) {
            throw new UserException(StatusCode.USER_EXCEPTION);
        } else {
            Long tipoff = userMapper.checkTipOff(user.getId());
            if (tipoff != null && tipoff > 0) {
                throw new UserException(StatusCode.ACCOUNT_FORBIDDEN);
            }
        }
        Preconditions.checkArgument(!StringUtils.isEmpty(loginDto.getPassword()), StatusCode.PASSWORD_NOT_EMPTY.msg());
        if (!Md5Util.matches(loginDto.getPassword(), user.getPasswordHash())) {
            throw new UserException(StatusCode.PASSWORD_ERROR);
        }
        // 判断以前的token
        if (StringUtils.isNotBlank(user.getToken())) {
            if (rwRedisService.hasKey(user.getToken())) {
                rwRedisService.delete(user.getToken());
            }
        }
        String token = tokenManagerService.createToken(ConvertUtil.UserToUserInfo(user));
        JSONObject rs = new JSONObject();
        rs.put("id", user.getId());
        rs.put("nickname", user.getNickname() == null ? "" : user.getNickname());
        rs.put("avatar", user.getAvatar() == null ? "" : user.getAvatar());
        rs.put("avatar_small", user.getAvatarSmall() == null ? "" : user.getAvatarSmall());
        rs.put("token", token);
        rs.put("completed", StringUtils.isNotBlank(user.getNickname()) && StringUtils.isNotBlank(user.getAvatar()));
        return rs;
    }

    @Override
    public List<JSONObject> getUserByNicknameOrPhone(String param) {
        List<User> userList = userMapper.getUserByNicknameOrPhone(param);
        List<JSONObject> rsList = new ArrayList<>();
        for (User user : userList) {
            JSONObject js = new JSONObject();
            js.put("id", user.getId());
            js.put("nickname", user.getNickname() == null ? "" : user.getNickname());
            js.put("avatar", user.getAvatar() == null ? "" : user.getAvatar());
            js.put("avatar_small", user.getAvatarSmall() == null ? "" : user.getAvatarSmall());
            rsList.add(js);
        }
        return rsList;
    }

    @Override
    public String getInviteCode() {
        UserInfo user = GlobalController.getNowUser();
        String existCode = inviteCodeMapper.getCodeByUserId(user.getId());
        // 如果这个用户已经存在一个邀请码，则直接返回，否则生成一个新的
        if (existCode != null) {
            return existCode;
        }
        String code = InviteCodeUtil.getInviteCode();
        InviteCode inviteCode = new InviteCode();
        inviteCode.setCode(code);
        inviteCode.setCreatedTime(Instant.now().getEpochSecond());
        inviteCode.setUserId(user.getId());
        inviteCodeMapper.insertSelective(inviteCode);
        return code;
    }

    @Override
    public boolean useInviteCode(String code) {
        // 判断邀请码是否存在
        InviteCode inviteCode = inviteCodeMapper.getByCode(code);
        if (inviteCode == null) {
            return false;
        }
        UserInfo user = GlobalController.getNowUser();
        // 判断当前用户是否已经使用过该邀请码
        if (inviteCodeRecordMapper.getCount(user.getId(), code) > 0) {
            return false;
        }

        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String todayInviteAmountKey = "o:invite:" + today + ":" + inviteCode.getUserId();
        // 今日邀请量+1
        rwRedisService.opsForValue().increment(todayInviteAmountKey, 1);
        rwRedisService.expire(todayInviteAmountKey, 24 * 60 * 60);
        // 总邀请量+1
        String totalInviteAmountKey = RedisKey.INVITE_CODE_TOTAL_AMOUNT_KEY + inviteCode.getUserId();
        // 因为totalInviteAmountKey设置了3天的过期时间
        if (rwRedisService.hasKey(totalInviteAmountKey)) {
            rwRedisService.opsForValue().increment(totalInviteAmountKey, 1);
        }
        InviteCodeRecord inviteCodeRecord = new InviteCodeRecord();
        inviteCodeRecord.setCode(code);
        inviteCodeRecord.setCreatedTime(Instant.now().getEpochSecond());
        inviteCodeRecord.setLookerUserId(user.getId());
        // 邀请码使用记录
        inviteCodeRecordMapper.insertSelective(inviteCodeRecord);
        return true;
    }

    @Override
    public JSONObject inviteCodeView() {
        UserInfo user = GlobalController.getNowUser();
        //
        InviteCode inviteCode = inviteCodeMapper.getByUserId(user.getId());
        if (inviteCode == null) {
            return new JSONObject();
        }
        long current = System.currentTimeMillis();
        long zero = current/(1000*3600*24)*(1000*3600*24) - TimeZone.getDefault().getRawOffset();
        zero = zero/1000;
        // 获取今日邀请量
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String todayInviteAmountKey = "o:invite:" + today + ":" + user.getId();
//        Integer todayInviteAmount = (Integer) rwRedisService.opsForValueRead().get(todayInviteAmountKey);
//        // 获取累计邀请数量
//        String totalInviteAmountKey = RedisKey.INVITE_CODE_TOTAL_AMOUNT_KEY + user.getId();
//        Integer totalInviteAmount = (Integer) rwRedisService.opsForValueRead().get(totalInviteAmountKey);
//        if (totalInviteAmount == null) {
//            totalInviteAmount = inviteCodeRecordMapper.getTotalInviteAmountByCode(inviteCode.getCode());
//            rwRedisService.opsForValue().set(totalInviteAmountKey, totalInviteAmount, 3, TimeUnit.DAYS);
//        }
        Integer todayInviteAmount = inviteCodeRecordMapper.selectToday(inviteCode.getCode(),zero,zero-86400);
        Integer totalInviteAmount = inviteCodeRecordMapper.selectTotal(inviteCode.getCode(),zero,zero-86400);
        JSONObject rs = new JSONObject();
        rs.put("todayInviteAmount", todayInviteAmount == null ? 0 : todayInviteAmount);
        rs.put("totalInviteAmount", totalInviteAmount == null ? 0 : totalInviteAmount);
        rs.put("inviteCode", inviteCode.getCode());
        return rs;
    }

    @Override
    public List<String> findPartAroundPeopleImgV3(Double[] point, Integer sexType, int v1RandomShowLimit) {

        return new ArrayList<>();
    }

}
